package com.harry.utility;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 注解工具类
 */
public abstract class AnnoHelper {

	public static <T> T findAnnoValue(Class<?> declaringClazz, String fieldName, String key, Class<T> tclass) {
		try {
			Object[] anno_method = findAnnoMethodByKey(declaringClazz, fieldName, key);
			if (anno_method == null) {
				return null;
			} else {
				Annotation anno = (Annotation) anno_method[0];
				Method keyMethod = (Method) anno_method[1];
				return tclass.cast(keyMethod.invoke(anno));
			}
		} catch (Exception e) {
			return null;
		}
	}

	public static Boolean isAnnoable(Class<?> declaringClazz, String fieldName, String key) {
		Boolean value = AnnoHelper.findAnnoValue(declaringClazz, fieldName, key, Boolean.class);
		return InnerUtils.ifNull(value, () -> Boolean.TRUE);
	}

	private static Object[] findAnnoMethodByKey(Class<?> declaringClazz, String fieldName, String key) throws Exception {
		Field declaredField = null;
		for (Class<?> tempClazz = declaringClazz; declaredField == null
				&& tempClazz != Object.class; tempClazz = tempClazz.getSuperclass()) {
			try {
				declaredField = tempClazz.getDeclaredField(fieldName);
			} catch (NoSuchFieldException e) {
			}
		}
		if (declaredField != null) {
			for (Annotation anno : declaredField.getAnnotations()) {
				Method[] ms = anno.getClass().getMethods();
				Set<String> keySet = Stream.of(ms).map(m -> m.getName()).collect(Collectors.toSet());
				if (keySet.contains(key)) {
					return new Object[] { anno, anno.getClass().getMethod(key) };
				}
			}
		}
		return null;
	}
}
